package com.zycfc.zsf.boot.distributedlock;

import com.zycfc.zsf.boot.redis.*;
import java.util.*;
import com.zycfc.zsf.boot.core.common.*;
import com.zycfc.zsf.boot.distributedlock.configuration.*;
import com.zycfc.zsf.boot.util.text.*;
import java.util.concurrent.locks.*;
import org.slf4j.*;

public class DistributedRedisLock implements IDistributedLock
{
    private static final Logger log;
    private static final long DEFAULT_EXPIRE = 5000L;
    private static final long DEFAULT_TRY_LOCK_TIME = 0L;
    private static final long DEFAULT_TRY_LOCK_INTERVAL = 50L;
    private static final String REDISOPERATER_BEAN_NAME = "redisOperater";
    private static final String DEFAULT_APP_NAME = "defaultAppName";
    private static final String REDIS_SEPARATOR = ":";
    private String appName;
    private String group;
    private String key;
    private Long expireTime;
    private Long tryLockTime;
    private Long tryLockInterval;
    private String value;
    private IRedisOperater redisOperater;
    
    public DistributedRedisLock(final String applicationName, final String namespace, final Long expireTime, final IRedisOperater redisOperater) {
        this.appName = applicationName;
        this.group = namespace;
        this.expireTime = 5000L;
        this.tryLockTime = 0L;
        this.tryLockInterval = 50L;
        this.value = UUID.randomUUID().toString();
        this.redisOperater = redisOperater;
    }
    
    protected DistributedRedisLock(final String group, final String key) {
        this(group, key, 5000L);
    }
    
    protected DistributedRedisLock(final String group, final String key, final Long expireTime) {
        this(group, key, expireTime, 0L);
    }
    
    protected DistributedRedisLock(final String group, final String key, final Long expireTime, final Long tryLockTime) {
        this(group, key, expireTime, tryLockTime, 50L);
    }
    
    protected DistributedRedisLock(final String group, final String key, final Long expireTime, final Long tryLockTime, final Long tryLockInterval) {
        this.key = key;
        this.group = group;
        this.expireTime = ((expireTime > 0L) ? expireTime : 5000L);
        this.tryLockTime = ((tryLockTime > 0L) ? tryLockTime : 0L);
        this.tryLockInterval = ((tryLockInterval > 0L) ? tryLockInterval : 50L);
        this.value = UUID.randomUUID().toString();
        this.redisOperater = (IRedisOperater)SpringContextHelper.getBean("redisOperater");
        final String confAppName = DistributedLockProperties.getAppName();
        this.appName = (StringUtils.isEmpty(confAppName) ? "defaultAppName" : confAppName);
    }
    
    @Override
    public boolean tryLock(final String key) {
        String finalKey = null;
        try {
            finalKey = (StringUtils.isEmpty(this.group) ? getFinalKey(key) : getFinalKey(this.group, key));
            if (this.tryLockTime <= 0L) {
                return this.redisOperater.setNxPx(finalKey, (Object)this.value, (long)this.expireTime);
            }
            final long timeout = System.currentTimeMillis() + this.tryLockTime;
            while (System.currentTimeMillis() < timeout) {
                if (this.redisOperater.setNxPx(finalKey, (Object)this.value, (long)this.expireTime)) {
                    return true;
                }
                LockSupport.parkUntil(System.currentTimeMillis() + this.tryLockInterval);
            }
        }
        catch (Throwable e) {
            DistributedRedisLock.log.error("tryDistributedRedisLock--key:{}--Exception", (Object)finalKey, (Object)e);
        }
        return false;
    }
    
    @Override
    public boolean tryLock() {
        return this.tryLock(this.key);
    }
    
    @Override
    public boolean releaseLock(final String key) {
        try {
            final String finalKey = StringUtils.isEmpty(this.group) ? getFinalKey(key) : getFinalKey(this.group, key);
            this.redisOperater.eval("if redis.call('get',KEYS[1]) == ARGV[1] then \n return redis.call('del',KEYS[1]) \n else return 0 \n end", finalKey, new Object[] { this.value });
            return true;
        }
        catch (Exception e) {
            DistributedRedisLock.log.error("releaseLock Exception,key={}", (Object)this.key, (Object)e);
            return false;
        }
    }
    
    @Override
    public boolean releaseLock() {
        return this.releaseLock(this.key);
    }
    
    private static String getFinalKey(final String... strs) {
        final StringBuffer lockKeyBuffer = new StringBuffer("lock");
        for (final String str : strs) {
            lockKeyBuffer.append(":").append(str.trim());
        }
        return lockKeyBuffer.toString();
    }
    
    static {
        log = LoggerFactory.getLogger((Class)DistributedRedisLock.class);
    }
}
